﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using DepIC;
using TeF.Runner.Services;

namespace TeF.Runner
{
    internal class Manager : IManager
    {
        private IReadOnlyContainer Container
        {
            get { return IoCHelper.Container; }
        }
        
        public ITestAssembly LoadTestAssembly(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
                throw new ArgumentException("path");

            var testAssembly = Container.Get<ITestAssemblyLoader>().Load(path);
            var testsInAssembly = Container.Get<ITestFinder>().GetTestsInAssembly(testAssembly);

            return testsInAssembly;
        }

        public void Run(IEnumerable<ITestEntity> testEntities)
        {
            if (testEntities == null)
                throw new ArgumentNullException("testEntities");

            RunInternal(testEntities);
        }

        public void RunAsync(IEnumerable<ITestEntity> testEntities)
        {
            if (testEntities == null)
                throw new ArgumentNullException("testEntities");

            var thread = new Thread(() => RunInternal(testEntities));
            thread.Start();
        }

        public string Run(string[] assemblyPathes, string reportDirectoryPath)
        {
            if (assemblyPathes == null)
                throw new ArgumentNullException("assemblyPathes");
            if (string.IsNullOrEmpty(reportDirectoryPath))
                throw new ArgumentException("reportDirectoryPath");
            if (!Directory.Exists(reportDirectoryPath))
                throw new ArgumentException("reportDirectoryPath");

            var testAssemblies = 
                assemblyPathes
                    .Distinct()
                    .Select(LoadTestAssembly)
                    .ToArray();

            Run(testAssemblies);

            var reportFilePath = Container.Get<IReportCreator>().CreateReport(reportDirectoryPath, testAssemblies);

            return reportFilePath;
        }

        private void RunInternal(IEnumerable<ITestEntity> testEntities)
        {
            if (testEntities == null)
                throw new ArgumentNullException("testEntities");

            var testsToRun = Container.Get<ITestFinder>().GetTestsToRun(testEntities.ToArray());

            Container.Get<ITestRunner>().RunTests(testsToRun);

            if (RunCompleted != null)
                RunCompleted(this, EventArgs.Empty);
        }

        public event EventHandler RunCompleted;
    }
}
